package com.javablog.controller;

import com.javablog.dto.ArticleDto;
import com.javablog.dto.UserSummaryDto;
import com.javablog.dto.response.MessageResponse;
import com.javablog.dto.response.PagedResponse;
import com.javablog.model.Article;
import com.javablog.model.Category;
import com.javablog.model.Tag;
import com.javablog.model.User;
import com.javablog.repository.ArticleRepository;
import com.javablog.repository.CategoryRepository;
import com.javablog.repository.TagRepository;
import com.javablog.repository.UserRepository;
import com.javablog.security.services.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@CrossOrigin(origins = "*", maxAge = 3600)
@RestController
@RequestMapping("/api/articles")
public class ArticleController {
    
    @Autowired
    private ArticleRepository articleRepository;
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private CategoryRepository categoryRepository;
    
    @Autowired
    private TagRepository tagRepository;
    
    @GetMapping
    public ResponseEntity<?> getAllArticles(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "createdAt") String sortBy,
            @RequestParam(defaultValue = "desc") String sortDir) {
        
        Sort.Direction direction = sortDir.equalsIgnoreCase("asc") ? Sort.Direction.ASC : Sort.Direction.DESC;
        Sort sort = Sort.by(direction, sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);
        
        Page<Article> articlesPage = articleRepository.findAll(pageable);
        
        List<ArticleDto> content = articlesPage.getContent().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        
        PagedResponse<ArticleDto> response = new PagedResponse<>(
                content,
                articlesPage.getNumber(),
                articlesPage.getSize(),
                articlesPage.getTotalElements(),
                articlesPage.getTotalPages(),
                articlesPage.isLast());
        
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<?> getArticleById(@PathVariable Long id) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        // 增加浏览量
        article.setViews(article.getViews() + 1);
        articleRepository.save(article);
        
        return ResponseEntity.ok(convertToDto(article));
    }
    
    @PostMapping
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> createArticle(@Valid @RequestBody ArticleDto articleDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        User user = userRepository.findById(userDetails.getId())
                .orElseThrow(() -> new RuntimeException("错误：用户未找到。"));
        
        Article article = new Article();
        article.setTitle(articleDto.getTitle());
        article.setContent(articleDto.getContent());
        article.setAuthor(user);
        
        if (articleDto.getCategoryId() != null) {
            Category category = categoryRepository.findById(articleDto.getCategoryId())
                    .orElseThrow(() -> new RuntimeException("错误：分类未找到。"));
            article.setCategory(category);
        }
        
        Set<Tag> tags = new HashSet<>();
        if (articleDto.getTagIds() != null && !articleDto.getTagIds().isEmpty()) {
            articleDto.getTagIds().forEach(tagId -> {
                Tag tag = tagRepository.findById(tagId)
                        .orElseThrow(() -> new RuntimeException("错误：标签未找到，ID: " + tagId));
                tags.add(tag);
            });
        }
        article.setTags(tags);
        
        articleRepository.save(article);
        
        return ResponseEntity.ok(new MessageResponse("文章创建成功!"));
    }
    
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> updateArticle(@PathVariable Long id, @Valid @RequestBody ArticleDto articleDto) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        // 只有文章作者或管理员可以更新文章
        if (!article.getAuthor().getId().equals(userDetails.getId()) && 
                !authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
            return ResponseEntity.badRequest().body(new MessageResponse("错误：没有权限更新此文章!"));
        }
        
        article.setTitle(articleDto.getTitle());
        article.setContent(articleDto.getContent());
        
        if (articleDto.getCategoryId() != null) {
            Category category = categoryRepository.findById(articleDto.getCategoryId())
                    .orElseThrow(() -> new RuntimeException("错误：分类未找到。"));
            article.setCategory(category);
        }
        
        if (articleDto.getTagIds() != null) {
            Set<Tag> tags = new HashSet<>();
            articleDto.getTagIds().forEach(tagId -> {
                Tag tag = tagRepository.findById(tagId)
                        .orElseThrow(() -> new RuntimeException("错误：标签未找到，ID: " + tagId));
                tags.add(tag);
            });
            article.setTags(tags);
        }
        
        articleRepository.save(article);
        
        return ResponseEntity.ok(new MessageResponse("文章更新成功!"));
    }
    
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> deleteArticle(@PathVariable Long id) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
        
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        // 只有文章作者或管理员可以删除文章
        if (!article.getAuthor().getId().equals(userDetails.getId()) && 
                !authentication.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("ROLE_ADMIN"))) {
            return ResponseEntity.badRequest().body(new MessageResponse("错误：没有权限删除此文章!"));
        }
        
        articleRepository.delete(article);
        
        return ResponseEntity.ok(new MessageResponse("文章删除成功!"));
    }
    
    @GetMapping("/user/{userId}")
    public ResponseEntity<?> getArticlesByUser(
            @PathVariable Long userId,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("错误：用户未找到。"));
        
        Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt"));
        Page<Article> articlesPage = articleRepository.findByAuthor(user, pageable);
        
        List<ArticleDto> content = articlesPage.getContent().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        
        PagedResponse<ArticleDto> response = new PagedResponse<>(
                content,
                articlesPage.getNumber(),
                articlesPage.getSize(),
                articlesPage.getTotalElements(),
                articlesPage.getTotalPages(),
                articlesPage.isLast());
        
        return ResponseEntity.ok(response);
    }
    
    @GetMapping("/search")
    public ResponseEntity<?> searchArticles(
            @RequestParam String keyword,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size) {
        
        Pageable pageable = PageRequest.of(page, size);
        Page<Article> articlesPage = articleRepository.searchByKeyword(keyword, pageable);
        
        List<ArticleDto> content = articlesPage.getContent().stream()
                .map(this::convertToDto)
                .collect(Collectors.toList());
        
        PagedResponse<ArticleDto> response = new PagedResponse<>(
                content,
                articlesPage.getNumber(),
                articlesPage.getSize(),
                articlesPage.getTotalElements(),
                articlesPage.getTotalPages(),
                articlesPage.isLast());
        
        return ResponseEntity.ok(response);
    }
    
    @PostMapping("/{id}/like")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> likeArticle(@PathVariable Long id) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        article.setLikes(article.getLikes() + 1);
        articleRepository.save(article);
        
        return ResponseEntity.ok(new MessageResponse("文章点赞成功!"));
    }
    
    @PostMapping("/{id}/dislike")
    @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
    public ResponseEntity<?> dislikeArticle(@PathVariable Long id) {
        Article article = articleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("错误：文章未找到。"));
        
        article.setDislikes(article.getDislikes() + 1);
        articleRepository.save(article);
        
        return ResponseEntity.ok(new MessageResponse("文章点踩成功!"));
    }
    
    private ArticleDto convertToDto(Article article) {
        ArticleDto articleDto = new ArticleDto();
        articleDto.setId(article.getId());
        articleDto.setTitle(article.getTitle());
        articleDto.setContent(article.getContent());
        articleDto.setViews(article.getViews());
        articleDto.setLikes(article.getLikes());
        articleDto.setDislikes(article.getDislikes());
        articleDto.setCommentCount(article.getComments().size());
        articleDto.setCreatedAt(article.getCreatedAt());
        articleDto.setUpdatedAt(article.getUpdatedAt());
        
        if (article.getCategory() != null) {
            articleDto.setCategoryId(article.getCategory().getId());
        }
        
        if (article.getTags() != null && !article.getTags().isEmpty()) {
            articleDto.setTagIds(article.getTags().stream()
                    .map(Tag::getId)
                    .collect(Collectors.toSet()));
        }
        
        // 设置作者信息
        UserSummaryDto authorDto = new UserSummaryDto();
        authorDto.setId(article.getAuthor().getId());
        authorDto.setUsername(article.getAuthor().getUsername());
        authorDto.setAvatar(article.getAuthor().getAvatar());
        authorDto.setBio(article.getAuthor().getBio());
        articleDto.setAuthor(authorDto);
        
        return articleDto;
    }
}